//
//  DeviceInfoGenerator.m
//  CodeHelper
//
//  Created by Rowling on 2023/5/23.
//

#import "DeviceInfoGenerator.h"
@interface DeviceInfoGenerator()
@property(strong, nonatomic) NSArray<NSString *> * infoKeys;
@property(strong, nonatomic) NSMutableArray<NSString *> * generatedStrings;
@property(strong, nonatomic) WriteInfo * info;

@end

@implementation DeviceInfoGenerator

- (NSMutableArray<NSString *> *)generatedStrings {
    if (_generatedStrings == nil) {
        _generatedStrings = [NSMutableArray array];
    }
    return  _generatedStrings;
}

- (instancetype)init {
    self = [super init];
    self.infoKeys = [self shuffleArray:self.infoKeys];
    self.info = [WriteInfo new];
    self.info.className = [NSString stringWithFormat:@"Device_%@", [self generateRandomWord:4]];
    self.info.getInfoFunctionName = @"getInfo";
    [self.generatedStrings addObject:self.info.className];
    [self.generatedStrings addObject:self.info.getInfoFunctionName];
    return  self;
}

- (NSArray *)infoKeys {
    return  @[
        @"mobilePhoneBrand",
        @"mobilePhoneModel",
        @"ramTotalSpace",
        @"networkCountryIso",
        @"recentDatetime",
        @"systemVersion",
        @"deviceId",
        @"manufacturer",
        @"bootTime",
        @"cpuCount",
        @"romFreeSpace",
        @"romTotalSpace",
        @"romUsedSpace",
        @"networkOperator",
        @"networkOperatorName",
        @"screenResolution",
        @"screenScale",
        @"emulator",
        @"charging",
        @"batterypercent",
        @"screenSize",
        @"screenLuminance",
        @"root",
        @"network",
        @"wifiName",
        @"routerMac",
        @"languageName",
        @"timezoneId",
        @"fcm"
             ];
}

-(void)write {
    
    NSMutableString * content = [NSMutableString string];

    Scope * sc = [self generateGetInfoFunction];
    
    [content appendFormat:@"import Foundation\n"];
    [content appendFormat:@"import CoreTelephony\n"];
    [content appendFormat:@"import SystemConfiguration.CaptiveNetwork\n"];
    [content appendFormat:@"import CommonCrypto\n"];
    [content appendFormat:@"import Alamofire\n"];
    if ([sc.topScope length] > 0) {
        [content appendFormat:@"%@\n", sc.topScope];
    }
    [content appendFormat:
     @"class %@ {\n"
     "\tprivate init() {\n\t%@\t}\n\n"
     "\tstatic let shared = %@()\n\n"
     "%@\n\n"
     ,self.info.className, sc.INITScope, self.info.className, sc.ivarScope];
    
    // getInfo
    [content appendFormat:@"%@", sc.mainFunc];
    [content appendFormat:@"}\n"];
    [content appendFormat:@"%@", sc.fileScope];

    NSLog(@"%@",content);
    [self writeFileToDownload:self.info.className suffix:@"swift" content:content];
}


-(Scope *)generateGetInfoFunction {
    Scope * sc = [Scope new];
    NSString * result = [self generateRandomWord:6];
    NSMutableString * content = [NSMutableString string];
    
    NSMutableString * subMethodsContent = [NSMutableString string];
    
    [content appendFormat:
     @"\tfunc %@() -> [String : Any] {\n"
     "\t\tvar %@ = [String : Any]()\n",
     self.info.getInfoFunctionName, result];
    
    for (NSString * key in self.infoKeys) {
        MatchCode * code = [self generateMethod:key];
        if (!content) {
            continue;
        }
        if (code.type == 0) {
            // 立即
            [content appendFormat:
             @"\t\t%@[\"%@\"] = %@\n",
             result, key, code.content];
        } else if (code.type == 1) {
            // 方法
            if (code.isOptional) {
                [content appendFormat:
                 @"\t\tif let %@ = %@() { \n"
                 "\t\t\t%@[\"%@\"] = %@\n"
                 "\t\t}\n",
                 code.content,code.content,
                 result, key, code.content];
            } else {
                [content appendFormat:
                 @"\t\t%@[\"%@\"] = %@()\n",
                 result, key, code.content];
            }
            [subMethodsContent appendFormat:
             @"%@\n\n",code.method];
        } else if (code.type == 2) {
            // 立即 + 方法
            if (code.domainReplace.length > 0) {
                NSString * rpStr = [code.domainReplace stringByReplacingOccurrencesOfString:@"${domain}" withString:result];
                rpStr = [rpStr stringByReplacingOccurrencesOfString:@"${domainKey}" withString:key];
                [content appendFormat:
                 @"%@\n",rpStr];
            }else if (code.isOptional) {
                NSString * tempIvar = [self generateRandomWord:5];
                [content appendFormat:
                 @"\t\tif let %@ = %@ { \n"
                 "\t\t\t%@[\"%@\"] = %@\n"
                 "\t\t}\n",
                 tempIvar,code.content,
                 result, key, tempIvar];
            } else {
                [content appendFormat:
                 @"\t\t%@[\"%@\"] = %@\n",
                 result, key, code.content];
            }
            
            if ([code.method length] > 0) {
                [subMethodsContent appendFormat:
                 @"%@\n\n",code.method];
            }
        }
        if ([code.fileScope length] > 0) {
            [sc.fileScope appendFormat:@"%@\n\n",code.fileScope];
        }
        
        if ([code.INITScope length] > 0) {
            [sc.INITScope appendFormat:@"%@",code.INITScope];
        }
        
        if ([code.ivarScope length] > 0) {
            [sc.ivarScope appendFormat:@"%@",code.ivarScope];
        }
        
        if ([code.topScope length] > 0) {
            [sc.topScope appendFormat:@"%@\n",code.topScope];
        }
        
        if (code.source) {
            [self writeFileToDownload:code.source.name suffix:code.source.suffix content:code.source.content];
        }
    }
    
    [content appendFormat:@"\t\treturn %@\n\n", result];
    [content appendFormat:@"\t}\n\n"];

    [content appendString:subMethodsContent];
    
    sc.mainFunc = content;
    return sc;
}

-(BOOL)writeFileToDownload:(NSString *)name suffix:(NSString *)suffix content:(NSString *)content {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES);
    NSString *downPath = [paths firstObject];
    NSString *destinationFilePath = [downPath stringByAppendingString:[NSString stringWithFormat:@"/%@.%@",name, suffix]];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL success = [fileManager createFileAtPath:destinationFilePath contents:[content dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
    if (!success) {
        NSLog(@"❌ %@.%@文件写出失败", name, suffix);
    }
    return success;
}


-(NSMutableString *)generateRandomWord:(NSInteger )length {
    NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
    NSMutableString *randomWord = [NSMutableString stringWithCapacity:length];
    for (int i = 0; i < length; i++) {
        NSUInteger randomIndex = arc4random() % [letters length];
        unichar randomChar = [letters characterAtIndex:randomIndex];
        while (randomChar == '_' && i == 0) {
            randomIndex = arc4random() % [letters length];
            randomChar = [letters characterAtIndex:randomIndex];
        }
        [randomWord appendFormat:@"%C", randomChar];
    }
    if ([self.generatedStrings containsObject:randomWord]) {
        randomWord = [self generateRandomWord:length];
    }
    [self.generatedStrings addObject:randomWord];
    return randomWord;
}

-(NSArray *)shuffleArray:(NSArray *)original {
    NSMutableArray * array = [NSMutableArray arrayWithArray:original];
    NSUInteger count = [array count];
    for (NSUInteger i = 0; i < count - 1; i++) {
        NSUInteger remainingCount = count - i;
        NSUInteger exchangeIndex = i + arc4random() % remainingCount;
        [array exchangeObjectAtIndex:i withObjectAtIndex:exchangeIndex];
    }
    return array;
}


-(MatchCode *)generateMethod:(NSString *)key {
    return [self readTemp:key];
}
        
// 读取模版
-(MatchCode *)readTemp:(NSString *)key {
    NSString * path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@_temp", key] ofType:nil];
    NSError *error = nil;
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
    NSArray<NSTextCheckingResult *> *matches = [self matches:fileContent reg:@"//\\s*temp_start_(\\d+)\\s([\\s\\S.]*?)\\s//\\s*temp_end"];
    int inddex = arc4random() % matches.count;
    
    NSTextCheckingResult * match = matches[inddex];
    if (match) {
        NSRange typeRange = [match rangeAtIndex:1]; // 获取组1的范围
        NSRange contentRange = [match rangeAtIndex:2]; // 获取组2的范围
        NSString * typeStr = [fileContent substringWithRange:typeRange]; // 提取组1的内容
        NSMutableString * content = [NSMutableString stringWithString:[fileContent substringWithRange:contentRange]]; // 提取组1的内容
        int type = [typeStr intValue];
        MatchCode * m = [MatchCode new];
        m.type = type;
        // 处理随机串
//        ${random_1}
        NSArray<NSTextCheckingResult *> *matches = [self matches:content reg:@"\\$\\{random_(\\d+)\\}"];
        NSMutableDictionary * dic = [NSMutableDictionary dictionary];
        [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSString * mathStr = [content substringWithRange:obj.range];
            if (dic[mathStr] == nil) {
                dic[mathStr] = [self generateRandomWord:arc4random() % 3 + 6];
            }
            [content replaceCharactersInRange:obj.range withString:dic[mathStr]];
        }];
        NSString * methdname = [self generateRandomWord:9];
        [content replaceOccurrencesOfString:@"${functionName}" withString:methdname options:NSCaseInsensitiveSearch range:NSMakeRange(0, content.length)];

        if (type == 0) {
            m.content = content;
        } else if (type == 1) {
            m.content = methdname;
            NSString * ret = [self matchWithString:content reg:@"func\\s+.*->\\s*([a-zA-Z0-9?_-]+)\\s*\\{" groupIndex:1];
            m.isOptional = [ret hasSuffix:@"?"];
            m.method = content;
        } else if (type == 2) {
            NSString * rightStr = [self matchWithString:content reg:[self method2Reg:@"replace"] groupIndex:1];
                m.content = rightStr;
            NSString * methodStr = [self matchWithString:content reg:[self method2Reg:@"method"] groupIndex:1];
                m.method = methodStr;
            NSString * optional = [self matchWithString:content reg:[self method2Reg:@"optional"] groupIndex:1];
            if ([optional isEqualToString:@"1"] || [optional isEqualToString:@"true"] || [[optional lowercaseString] isEqualToString:@"yes"]) {
                m.isOptional = true;
            }
            NSString * fileScope = [self matchWithString:content reg:[self method2Reg:@"fileScope"] groupIndex:1];
            NSString * initScope = [self matchWithString:content reg:[self method2Reg:@"initScope"] groupIndex:1];
            NSString * ivarScope = [self matchWithString:content reg:[self method2Reg:@"ivarScope"] groupIndex:1];
            NSString * topScope = [self matchWithString:content reg:[self method2Reg:@"topScope"] groupIndex:1];
            NSString * domainReplace = [self matchWithString:content reg:[self method2Reg:@"domainReplace"] groupIndex:1];
            NSString * source = [self matchWithString:content reg:[self method2Reg:@"source"] groupIndex:1];
            
            m.fileScope = fileScope;
            m.INITScope = initScope;
            m.ivarScope = ivarScope;
            m.domainReplace = domainReplace;
            m.topScope = topScope;
            if ([source length] > 0) {
                NSString * sourceName = [self matchWithString:content reg:[self source2Reg:@"name"] groupIndex:1];
                NSString * sourceSuffix = [self matchWithString:content reg:[self source2Reg:@"suffix"] groupIndex:1];
                NSString * sourceContent = [self matchWithString:content reg:[self source2Reg:@"content"] groupIndex:1];
                if (sourceName.length > 0 && sourceSuffix.length > 0 && sourceContent.length > 0) {
                    Source * s = [Source new];
                    s.name = sourceName;
                    s.suffix = sourceSuffix;
                    s.content = sourceContent;
                    m.source = s;
                }
            }
        }
        return m;
    } else {
        return nil;
    }
}

-(NSString *)method2Reg:(NSString *)key {
    NSString * scopeSubfix = @"->\\(\\s?([.\\s\\S]*?)\\)<-";
    return [NSString stringWithFormat:@"%@%@",key ,scopeSubfix];
}

-(NSString *)source2Reg:(NSString *)key {
    NSString * scopeSubfix = @"=>\\(\\s?([.\\s\\S]*?)\\)<=";
    return [NSString stringWithFormat:@"%@%@",key ,scopeSubfix];
}

-(NSArray<NSTextCheckingResult *> *)matches:(NSString *)orgStr reg:(NSString *)reg {
    NSString * regularExpression = reg;
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines | NSRegularExpressionUseUnixLineSeparators error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:orgStr options:0 range:NSMakeRange(0, orgStr.length)];
    return  matches;
}

// 通过正则抽取对应组
-(NSString *)matchWithString:(NSString *)str
                         reg:(NSString *)reg
                  groupIndex:(NSInteger)index{
    NSString * regularExpression = [NSString stringWithFormat:@"%@", reg];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines | NSRegularExpressionUseUnixLineSeparators error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:str options:0 range:NSMakeRange(0, str.length)];
    if (matches.count == 0) {
        return  nil;
    }
    NSTextCheckingResult * match = matches[0];
    NSRange grange = [match rangeAtIndex:index];
    NSString * r = [str substringWithRange:grange];
    return  r;
}

        
        

@end

@implementation WriteInfo

@end


@implementation MatchCode

@end

@implementation Scope
- (NSMutableString *)fileScope {
    if (_fileScope == nil) {
        _fileScope = [NSMutableString string];
    }
    return  _fileScope;
}

- (NSMutableString *)INITScope {
    if (_INITScope == nil) {
        _INITScope = [NSMutableString string];
    }
    return  _INITScope;
}

- (NSMutableString *)ivarScope {
    if (_ivarScope == nil) {
        _ivarScope = [NSMutableString string];
    }
    return  _ivarScope;
}

- (NSMutableString *)topScope {
    if (_topScope == nil) {
        _topScope = [NSMutableString string];
    }
    return  _topScope;
}
@end

@implementation Source

@end
